home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
prog
/
yamp2.zip
/
VIRTGRAF.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-17
|
18KB
|
676 lines
/*
YAMP - Yet Another Matrix Program
Version: 1.2
Author: Mark Von Tress, Ph.D.
Date: 01/23/92
Copyright(c) Mark Von Tress 1992
Portions of this code are (c) 1991 by Allen I. Holub and are used by
permission
DISCLAIMER: THIS PROGRAM IS PROVIDED AS IS, WITHOUT ANY
WARRANTY, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR DISCLAIMS
ALL LIABILITY FOR DIRECT OR CONSEQUENTIAL DAMAGES RESULTING
FROM USE OF THIS PROGRAM.
*/
#include "virt.h"
Axis::Axis( VMatrix &grf_vec, int col, int pixels, int pxlspplot)
{
Dispatch->Inclevel();
getlinesettings( &lineinfo );
valmin=0;
step=0;
ir=0;
ifault=0;
iv=30;
maxpr = 6;
mpv=pxlspplot;
fmn = fmx = grf_vec.m(1,col);
double temp;
for( int i=2; i<=grf_vec.r; i++){
temp = grf_vec.m(i,col);
fmn = ( temp < fmn ) ? temp : fmn;
fmx = ( temp > fmx ) ? temp : fmx;
}
if( fmn == fmx ){
fmx = fmn + 0.5;
fmn = fmn - 0.5;
}
vals = new double[iv];
getvals( fmn, fmx, pixels, vals, &offset, &ifact, &nvals, &irprin);
Vals = new VMatrix;
*Vals = Fill( nvals,1, 0);
for( i=0; i < nvals; i++){
double temp = (irprin != 0 )?
floor( 0.5 + vals[i]*exp(((double)irprin)*log(10.0)) )
*exp(-((double)irprin)*log(10.0)):
vals[i];
Vals->M(i+1,1) = temp;
}
Dispatch->Declevel();
}
Axis::~Axis( void )
{
delete vals;
delete Vals;
}
double Axis::dmax( double x, double y )
{
return ( (x>y) ? x: y);
}
void Axis::scale(double fmn, double fmx, int n, int mpv,
double *valmin, double *step, int *nvals,int *ir, int *ifault)
{ double unit[13]={ 0, 12,15,20,25,30,40,50,60,80,100,120,150};
double tol = 5.0e-6, bias = 1.0e-5, cover = 0.7, temp;
int i,j,minn = 2, maxn = 10000;
char buf[80] = {'\0'};
double fmax, fmin, finter, s, aj, tstep;
int nunit = 12;
fmax = fmx;
fmin = fmn;
*ifault = 0;
if (fmax < fmin) *ifault++;
if ( (n<minn)||(n>maxn)) *ifault += 2;
if ((mpv<=0)||(mpv>=n)) *ifault += 4;
if (*ifault) {
sprintf(buf, "SCALE: bad parameters in scale irprn = %d", *ifault);
closegraph();
Dispatch->Nrerror( buf );
}
*nvals = 1+(n-1)/mpv;
if ((fmax-fmin)<=(tol*((double)dmax(fabs(fmax),fabs(fmin))))){
*ifault = -1;
if(fmax<0) fmax = 0;
if(fmax==0) fmax = 1;
if(fmax>0) fmin = 0;
}
finter = ((double)n)/((double)mpv);
s = (fmax-fmin)*(1.0+2.0*bias)/finter;
*ir = 0;
while( s <= 10.0){
s *= 10;
(*ir)++;
}
while(s > 100 ) {
s /= 10;
(*ir)--;
}
i=0;
while( s > unit[i] ) i++;
LABEL1:
*step = unit[i]*exp( -((double)(*ir))*log(10) );
aj = 0;
LABEL2:
do{
aj += 1.0;
} while( (unit[i]-0.1) > ( floor((unit[i]+0.1)/aj)*aj ) );
tstep = (*step)/aj;
temp = fmin/tstep + aj*( 0.5/((double)mpv) - finter*bias);
*valmin = floor(temp)*tstep;
if( (temp<0) && (temp!=floor(temp))) (*valmin) -= tstep;
if (fmax < ((*valmin)+(*step)*(finter*(1.0-bias)-0.5/ ((double)mpv) ) ))
goto LABEL3;
if((unit[i]/unit[i+1]*(1.0-1.0/(aj*finter))) < cover) goto LABEL2;
i++;
if( i == nunit ) printf("problem");
goto LABEL1;
LABEL3:
for( j=1; j<=2; j++){
aj *= 10;
if( (unit[i] - 0.1 ) < ( floor((unit[i]+0.1)/aj)*aj) ) (*ir) -= 1;
}
} /* scale */
void Axis::axis(double valmin,double step,int nvals, int maxpr,int ir,
int *irprin, double *offset, int *ifact, double *vals, int iv,
int * ifault)
{
int irmax = 200, mprmax = 20;
double fmax, tmax, fl, fs, vstep,vmin, temp1=0, temp2=0;
double dtemp1=0, dtemp2=0;
int i,il,is,it,ilprin;
char buf[80] = {'\0'};
*ifault = 0;
if ( nvals < 2 ) (*ifault)++;
fmax = valmin + step*((double)(nvals-1));
if ( (nvals >= 2) && (fmax <= valmin)) (*ifault) += 2;
if ( (maxpr < 2) || (maxpr > mprmax) ) (*ifault) += 4;
if (nvals > iv) (*ifault) += 8;
if ( ir > irmax ) (*ifault) += 16;
if ( *ifault ){
sprintf(buf, "Axis: bad parameters in axis: error %d", *ifault);
closegraph();
Dispatch->Nrerror( buf );
}
tmax = exp( ((double)maxpr)*log(10.0) );
fl = fabs(fmax);
fs = fabs(valmin);
il = 0;
while( !( (fl < 1.0) && (fs < 1.0)) ){
fl /= 10;
fs /= 10;
il++;
}
while( !( (fl >= 0.1 ) || ( fs >= 0.1 )) ) {
fl *= 10;
fs *= 10;
il -= 1;
}
is = il + ir;
it = is;
if ((valmin <= 0.0 ) && ( fmax >= 0.0) ) goto LABEL50;
LABEL40:
fl =((double) modf( fl, &dtemp1))*10;
fs =((double) modf( fs, &dtemp2))*10;
if ( it <= 0 ){
closegraph();
Dispatch->Nrerror( "Axis: error 16 in axis ");
}
if ( ((int)floor( fl )) !=((int) floor(fs)) ) goto LABEL50;
it--;
goto LABEL40;
LABEL50:
*ifact = 0;
*offset = 0.0;
*irprin = ( ir > 0 )? ir : 0;
ilprin = ( il > 0 )? il : 0;
if ( ((*irprin)+ilprin) <= maxpr ) goto LABEL70;
if( is <= maxpr ) goto LABEL60;
*irprin = maxpr - 1;
*ifact = (it > maxpr)? it: maxpr ;
*ifact = (*ifact) - 1 - ir;
goto LABEL70;
LABEL60:
*ifact = il -1;
*irprin = is - 1;
LABEL70:
fs = exp(-((double)(*ifact))*log(10.0) );
vstep = step*fs;
vmin = valmin*fs;
if (!( is <= maxpr)){
*offset = floor( vmin / 10.0)*10;
vmin -= (*offset);
}
for( i=0; i<nvals; i++){
vals[i] = vmin;
vmin += vstep;
}
fs = pow( 0.1, ((double)(*irprin)) );
temp1 = fabs( vals[0])*fs + 0.5;
temp2 = fabs( vals[nvals-1]) * fs + 0.5;
if ( (temp1 < tmax ) && (temp2 < tmax ) ) return;
il++;
is++;
it++;
goto LABEL50;
} /* end axis */
/* get scale and axis Applied Statistics algorithm 168 */
void Axis::getvals(double fmn, double fmx, int n, double *vals,
double *offset,int *ifact,int *nvals,int *irprin)
{
scale(fmn, fmx, n, mpv, &valmin, &step, nvals, &ir, &ifault);
axis( valmin, step, *nvals, maxpr,ir, irprin, offset, ifact,
vals, iv, &ifault);
//
// the following code fixes an axis where data is out of range
//
double st = Rescale( step );
double t = Rescale( fmn );
double trace;
int down=0, up=0;
if ( t < vals[0] )
for( trace = vals[0];(t < trace) && (down + *nvals < iv);
down++, trace -= st);
t = Rescale( fmx );
if ( t > vals[*nvals-1] )
for( trace = vals[*nvals-1];(t > trace) && (up+down+*nvals < iv);
up++, trace += st);
if( down+up+*nvals >= iv ){
// prevent a writeover past the end of vals
ifault = 8;
char buf[80] = { '\0' };
sprintf(buf, "Axis: bad parameters in axis: error %d", ifault);
closegraph();
Dispatch->Nrerror( buf );
}
t = vals[0] - ((double) down)*st;
for( int i=0; i< down+up+*nvals; i++) {
vals[i] = t;
t+=st;
}
*nvals += down+up;
}
strtype Axis::GetAxisLabel( strtype &name)
{
char xo[20]={'\0'}, xi[20]={'\0'};
char buf[80]={'\0'};
strtype newname;
newname = name + " ";
gcvt(offset, 8, buf);
strcpy(xo,(const char *) buf);
gcvt(ifact, 8, buf);
strcpy(xi,(const char *) buf);
if ( offset && ifact )
newname = newname + "((x+" + xo +")*10**" + xi + ")";
if ( !offset && ifact )
newname = newname + "(x*10**" + xi + ")";
if ( offset && !ifact )
newname = newname + "(x+" + xo + ")";
return newname;
}
double Axis::Rescale( double x )
{
static double log10 = log(10.0);
double xo = x+offset;
double si = ( xo <= 0.0 ) ? -1.0: 1.0;
double xv = ( xo == 0.0 ) ? 0.0 :
si*exp( log(fabs(xo))-((double)ifact)*log10 );
return xv;
}
//////////////////////// yaxis
YAxis::YAxis( VMatrix &grf, int xxlen, int yylen, int ww, int hh,
int bbmarg, int uumarg, int llmarg, int rrmarg):
Axis( grf, 4, yylen, yylen/hh )
{
Dispatch->Inclevel();
h = hh;
w = ww;
bmarg = bbmarg;
umarg = uumarg;
lmarg = llmarg;
rmarg = rrmarg;
ylen = yylen;
xlen = xxlen;
maxy = (Mmax( *Vals )).m(3,1);
miny = (Mmin( *Vals )).m(3,1);
deltay = ( fabs(maxy-miny) < 1.0e-10) ? 1.1*miny : maxy - miny;
deltay = ((double)ylen)/deltay;
Dispatch->Cleanstack();
Dispatch->Declevel();
}
void YAxis::Show( boolean gridon )
{
// show yaxis
char *buf = new char[80];
strtype *junk = new strtype;
setviewport( lmarg, umarg, rmarg, bmarg, 1 );
line( 0,0, 0, ylen+1);
setviewport( 0, umarg-h, lmarg, bmarg+h, 1);
settextjustify( RIGHT_TEXT, CENTER_TEXT );
int tickloc;
for( int i=1; i<=nvals; i++){
double temp = Vals->m(i,1);
tickloc =ylen-(int)( deltay*( temp - miny ) )+h;
gcvt( temp, (maxpr+2), buf);
*junk = "";
*junk = *junk + buf + " ";
outtextxy( lmarg, tickloc, junk->StringAddress() );
line( lmarg-w+1, tickloc-1, lmarg, tickloc-1 );
}
if( gridon ){
setviewport( lmarg, umarg-h, rmarg, bmarg+h, 1);
setlinestyle( lineinfo.linestyle, lineinfo.upattern, NORM_WIDTH);
for( int i=1; i<=nvals; i++){
double temp = Vals->m(i,1);
tickloc =ylen-(int)( deltay*( temp - miny ) )+h;
line( 0, tickloc-1, xlen, tickloc-1);
}
setlinestyle( lineinfo.linestyle, lineinfo.upattern, THICK_WIDTH);
}
setviewport( lmarg, umarg, rmarg, bmarg, 1 );
delete buf;
delete junk;
}
//////////// xaxis
XAxis::XAxis( VMatrix &grf, int xxlen, int yylen, int ww, int hh,
int bbmarg, int uumarg, int llmarg, int rrmarg):
Axis( grf, 3, xxlen, xxlen/ww )
{
Dispatch->Inclevel();
xlen = xxlen;
ylen = yylen;
w = ww;
h = hh;
bmarg = bbmarg;
umarg = uumarg;
lmarg = llmarg;
rmarg = rrmarg;
maxx = (Mmax( *Vals )).m(3,1);
minx = (Mmin( *Vals )).m(3,1);
deltax = (fabs(maxx-minx) < 1.0e-10) ? 1.1*minx : maxx-minx;
deltax = ((double)xlen)/deltax;
Dispatch->Cleanstack();
Dispatch->Declevel();
}
void XAxis::Show( boolean gridon )
{
char *buf = new char[80];
setviewport( lmarg, umarg, rmarg, bmarg, 1 );
line( 0,ylen, xlen, ylen);
int mdelta = w*(maxpr+2)/2 + w;
setviewport( lmarg-mdelta, bmarg, rmarg+mdelta, bmarg+5*h, 1);
settextjustify( CENTER_TEXT, TOP_TEXT );
int tickloc;
for( int i=1; i<=nvals; i++){
double temp = Vals->m(i,1);
tickloc = mdelta + (int)( deltax*(temp - minx ) );
gcvt( temp, (maxpr+2), buf);
outtextxy( tickloc , h, buf);
line( tickloc+1, 0, tickloc+1, h/2);
}
if( gridon ){
setviewport( lmarg-mdelta, umarg, rmarg+mdelta, bmarg, 1);
setlinestyle( lineinfo.linestyle, lineinfo.upattern, NORM_WIDTH);
for( int i=1; i<=nvals; i++){
double temp = Vals->m(i,1);
tickloc = mdelta + (int)( deltax*(temp - minx ) );
line( tickloc+1, 0, tickloc+1, ylen);
}
setlinestyle( lineinfo.linestyle, lineinfo.upattern, THICK_WIDTH);
}
setviewport( lmarg, umarg, rmarg, bmarg, 1 );
delete buf;
}
/////////////////////////////// graph matrix class
GMatrix::GMatrix( void )
{
title = new strtype;
title2= new strtype;
xname = new strtype;
yname = new strtype;
PathToDriver = new strtype;
hrefs = new double[20];
vrefs = new double[20];
graphnum = 0;
nhrefs = nvrefs = -1;
RectangleOn = TTRUE;
XGridOn = YGridOn = FFALSE;
grf = new VMatrix("graph", 1, 4);
}
GMatrix::GMatrix( VMatrix &ROp, int symbol)
{
Dispatch->Inclevel();
nvrefs = nhrefs = -1;
title = new strtype;
*title = ROp.Getname(ROp);
title2= new strtype;
xname = new strtype;
yname = new strtype;
PathToDriver = new strtype;
hrefs = new double[20];
vrefs = new double[20];
graphnum = 1;
RectangleOn = TTRUE;
XGridOn = YGridOn = FFALSE;
grf = new VMatrix("graph", 1, 4);
int n = ROp.r;
printf("\nMaking a Graph\n");
*grf =
Ch( Fill(n,1, (double)graphnum), Ch(Fill(n,1, (double)symbol), ROp));
Dispatch->Declevel();
}
GMatrix::~GMatrix( void )
{
delete grf;
delete title;
delete title2;
delete xname;
delete yname;
delete PathToDriver;
delete hrefs;
delete vrefs;
}
void GMatrix::Href( double href )
{
hrefs[ ++nhrefs % 20 ] = href;
}
void GMatrix::Vref( double vref )
{
vrefs[ ++nvrefs % 20 ] = vref;
}
void GMatrix::AddVec( VMatrix &ROp, int symbol)
{
Dispatch->Inclevel();
VMatrix *temp = new VMatrix;
graphnum++;
int n = ROp.r;
printf("\nAppending a new graph\n");
*temp =
Ch( Fill(n,1,(double)graphnum), Ch(Fill(n,1,(double)symbol), ROp));
*grf = Cv( *grf, *temp);
delete temp;
Dispatch->Declevel();
}
int GMatrix::gprintf( int *xloc, int *yloc, char *fmt, ... )
{
va_list argptr; // Argument list pointer
char str[140]; // Buffer to build sting into
int cnt; // Result of SPRINTF for return
va_start( argptr, fmt ); // Initialize va_ functions
cnt = vsprintf( str, fmt, argptr ); // prints string to buffer
outtextxy( *xloc, *yloc, str ); // Send string in graphics mode
*yloc += textheight( "H" ) + 2; // Advance to next line
va_end( argptr ); // Close va_ functions
return( cnt ); // Return the conversion count
}
void GMatrix::Pause(void)
{
static char msg[] = "Esc aborts or press a key...";
int c;
c = getch();
if( 0x1b == c ){
closegraph();
exit( 1 );
}
if( 0 == c ){
c = getch();
}
cleardevice();
restorecrtmode();
}
void GMatrix::plotpoint( int ix, int iy, int symbol )
{
char str[2] = { (char) symbol, '\0'};
outtextxy( ix, iy, str );
}
void GMatrix::Show( void )
{
Dispatch->Inclevel();
GraphDriver = DETECT;
// GraphDriver = CGA;
// GraphMode = CGAHI;
initgraph( &GraphDriver, &GraphMode, PathToDriver->StringAddress() );
ErrorCode = graphresult();
if( ErrorCode != grOk ){
printf(" Graphics System Error: %s\n", grapherrormsg( ErrorCode ) );
exit( 1 );
}
cleardevice();
MaxColors = getmaxcolor() + 1;
MaxX = getmaxx();
MaxY = getmaxy(); // Read size of screen
getviewsettings( &viewinfo );
getlinesettings( &lineinfo );
setcolor( MaxColors -1 );
setviewport( 0,0, MaxX, MaxY, 1);
settextjustify( CENTER_TEXT, CENTER_TEXT );
int x = MaxX/2, y = 4;
gprintf( &x, &y, title->StringAddress() );
gprintf( &x, &y, title2->StringAddress() );
int h = textheight( "H" );
int w = textwidth( "Z" );
int lmarg = 10*w, rmarg = MaxX - 10 * w, umarg = 5*h, bmarg = MaxY-5*h;
setviewport( lmarg, umarg-1, rmarg, bmarg, 1 );
getviewsettings( &viewinfo );
int xlen = viewinfo.right - viewinfo.left;
int ylen = viewinfo.bottom - viewinfo.top;
setlinestyle( lineinfo.linestyle, lineinfo.upattern, THICK_WIDTH);
if( RectangleOn ) rectangle( 0,0, xlen, ylen);
///////////// draw axies
YAxis *yaxis = new YAxis( *grf, xlen, ylen, w, h, bmarg, umarg, lmarg, rmarg);
yaxis->Show(YGridOn);
XAxis *xaxis = new XAxis( *grf, xlen, ylen, w, h, bmarg, umarg, lmarg, rmarg);
xaxis->Show(XGridOn);
////////////// plot points
setlinestyle( lineinfo.linestyle, lineinfo.upattern, NORM_WIDTH);
setviewport( lmarg, umarg, rmarg, bmarg, 1 );
settextjustify( CENTER_TEXT, CENTER_TEXT );
int lx, ly, ix, iy, cnter = 1;
boolean newgraph = TTRUE;
double deltax = ((double)xlen)/(xaxis->maxx - xaxis->minx);
double deltay = ((double)ylen)/(yaxis->maxy - yaxis->miny);
for( int i=1; i<=grf->r; i++){
if( cnter != ((int) grf->m(i,1) ) ){
cnter++;
newgraph = TTRUE;
}
double symbol = grf->m(i,2);
double tempx = xaxis->Rescale(grf->m(i,3));
double tempy = yaxis->Rescale(grf->m(i,4));
ix = (int) ( ( tempx - xaxis->minx)*deltax );
iy = ylen - (int) ( ( tempy - yaxis->miny)*deltay );
plotpoint( ix, iy , abs(symbol) );
if( symbol <= 0.0 ){
if ( !newgraph ) line( lx, ly, ix, iy );
newgraph = FFALSE;
}
lx = ix;
ly = iy;
}
if( nhrefs > -1 ){
int indx = ( nhrefs > 19 ) ? 19: nhrefs;
for( i=0; i<= indx; i++){
double temph = yaxis->Rescale(hrefs[i]);
iy = ylen - ( (int) (( temph-yaxis->miny)*deltay) );
line( 0, iy, xlen, iy );
}
}
if( nvrefs > -1){
int indx = ( nvrefs > 19 ) ? 19: nvrefs;
for( i=0; i<= indx; i++){
double tempv = xaxis->Rescale(vrefs[i]);
ix = (int) ( (tempv - xaxis->minx)*deltax );
line( ix, 0, ix, ylen );
}
}
/////////// display axis labels
setviewport( 0,0, MaxX, MaxY, 1 );
strtype *ylabel = new strtype;
*ylabel = yaxis->GetAxisLabel( *yname );
x = lmarg;
y = umarg - h - 3;
gprintf( &x, &y, ylabel->StringAddress() );
strtype *xlabel = new strtype;
*xlabel = xaxis->GetAxisLabel( *xname );
y = bmarg + 3*h + h/2 + 2;
x = MaxX/2;
gprintf(&x, &y, xlabel->StringAddress() );
Pause();
delete xaxis;
delete yaxis;
delete xlabel;
delete ylabel;
Dispatch->Cleanstack();
Dispatch->Declevel();
}